// ///////////////////////////// MIT License //////////////////////////////////// //
//                                                                                //
// Copyright (c) 2010 David Zsolt Manrique                                        //
//                    david.zsolt.manrique@gmail.com                              //
//                                                                                //
// Permission is hereby granted, free of charge, to any person obtaining a copy   //
// of this software and associated documentation files (the "Software"), to deal  //
// in the Software without restriction, including without limitation the rights   //
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      //
// copies of the Software, and to permit persons to whom the Software is          //
// furnished to do so, subject to the following conditions:                       //
//                                                                                //
// The above copyright notice and this permission notice shall be included in     //
// all copies or substantial portions of the Software.                            //
//                                                                                //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     //
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       //
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    //
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         //
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  //
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN      //
// THE SOFTWARE.                                                                  //
//                                                                                //
// ////////////////////////////////////////////////////////////////////////////// //

//!
//!  Description: recommended fitting algorithm
//!
//!  Levenberg-Marquardt minimization and curve fitting 
//!  Ref:
//!    Is Levenberg-Marquardt the Most Efficient Optimization Algorithm for
//!    Implementing Bundle Adjustment?
//!    Manolis I.A. Lourakis and Antonis A. Argyros
//!    Institute of Computer Science, Foundation for Research and Technology - Hellas
//!    Vassilika Vouton, P.O. Box 1385, GR 711 10, Heraklion, Crete, GREECE lourakis,argyros@ics.forth.gr


#include "fit.h"


bool operator >>= (const std::vector<std::string> & input_lines,fit_levenberg_marquardt & get)
{
	std::vector<std::string> block;
    io::parse_block("<levenberg-marquardt-fit>","<\\levenberg-marquardt-fit>",input_lines,block);
	get.deviation = 0.0;
	get.m = 0;
	get.n = 0;
	get.k = 0;
	get.tau = 1.0e-3;
    get.e1 = 1.0e-12;
    get.e2 = 1.0e-12;
    get.kmax = 2000;
    for(std::vector<std::string>::iterator line = block.begin(); line != block.end(); line++)
    if(io::match("tau %1",*line,&get.tau)) ;
    else if (io::match("eps_1 %1",*line,&get.e1)) ;
    else if (io::match("eps_2 %1",*line,&get.e2)) ;
    else if (io::match("max_it %1",*line,&get.kmax)) ;
    else throw std::runtime_error("Syntax error: "+*line);
	if(block.size() == 0) return false;
	return true;
}

std::ostream & operator << (std::ostream & os,const fit_levenberg_marquardt & get)
{
	os << "<fit-report>" << std::endl;
	os << "Number of different structure : " << get.n << std::endl;
	os << "Number of independent parameter : " << get.m << std::endl;
	os << "Number of iteration : " << get.k << std::endl;
	if(get.k >= get.kmax) 
		os << " >>> Maximum "<< get.kmax << " iteration achieved! <<< " << std::endl; 
	os << "Largest deviation : " << get.deviation << std::endl;
	os << "<\\fit-report>" << std::endl;
	return os;
}


    

const std::vector<std::string> & operator >> (const std::vector<std::string> & input_lines,varname_t & get)
{
	std::vector<std::string> block;
	io::parse_block("<variable-name>","<\\variable-name>",input_lines,block);
	get.append("energy");
	for(std::vector<std::string>::iterator line = block.begin(); line != block.end(); line++)
	if(io::match("%1",*line,&get))
	{ break; }
	return input_lines;
}

const std::vector<std::string> & operator >> (const std::vector<std::string> & input_lines,xyzfilelist_t & get)
{
	std::vector<std::string> block;
	io::parse_block("<xyz>","<\\xyz>",input_lines,block);
	std::string fn;
	for(std::vector<std::string>::iterator line = block.begin(); line != block.end(); line++)
	if(io::match("%1",*line,&fn)) 
	{ get.push_back(fn); }
	return input_lines;
}

